home *** CD-ROM | disk | FTP | other *** search
- /* Program to unsqueeze files formed by sq.com
- *
- *
- *
- */
- /* CHANGE HISTORY:
- * 1.3 Close inbuff to avoid exceeding maximum number of
- * open files. Includes rearranging error exits.
- * 1.4 Add -count option to allow quick inspection of files.
- * 1.5 Break up long lines of introductory text
- * 1.5 -count no longer appends formfeed to preview of each file.
- * -fcount (-f10, -F10) does append formfeed.
- * 2.0 hacked for MSDOS, removed manual input, added usage print.
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #define RECOGNIZE 0xFF76 /* unlikely pattern */
- #define DLE 0x90 /* *** Stuff for first translation module *** */
- #define SPEOF 256 /* special endfile token */
- #define NUMVALS 257 /* 256 data values plus SPEOF*/
- #define LARGE 30000
- #define ERROR -1
-
- unsigned crc; /* error check code */
- char outdrv[3]; /* current output drive (string) */
-
- struct { /* Decoding tree */
- int children[2]; /* left, right */
- } dnode[NUMVALS - 1];
-
- int bpos; /* last bit position read */
- int curin; /* last byte value read */
- int repct; /*Number of times to retirn value*/
- int value; /*current byte value or EOF */
- char origname[14]; /* Original file name without drive */
-
- #define VERSION "2.0 17 Jan. 83"
-
- /* This must follow all include files */
- unsigned dispcnt; /* How much of each file to preview */
- char ffflag; /* should formfeed separate preview from
- different files */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int i,c;
- char inparg[16]; /* parameter from input */
-
- dispcnt = 0; /* Not in preview mode */
-
- printf("File unsqueezer version 2.00 by Richard Greenlaw\n");
- printf("251 Colony Ct. Gahanna OH 43230\n");
-
- /* Initialize output drive to default drive */
- outdrv[0] = '\0';
- /* But prepare for a specific drive */
- outdrv[1] = ':';
- outdrv[2] = '\0'; /* string terminator */
-
- /* Process the parameters in order */
- for(i = 1; i < argc; ++i)
- obey(argv[i]);
-
- if(argc < 2) {
- printf(" Useage:\n");
- printf(" USQ item ...\n");
- printf(" where ... represents more (optional) items and\n");
- printf(" 'item' is either:\n");
- printf(" drive: to change the output drive\n");
- printf(" file input file\n");
- printf(" drive:file input file\n");
- printf(" -count Previewing feature: redirects output\n");
- printf(" -fcount Same as -count except formfeed\n");
- printf(" appended to preview of each file.\n");
- printf(" Example: -f10.\n");
- }
- exit();
- }
-
- obey(p)
- char *p;
- {
- char *q;
-
- if(*p == '-') {
- if(ffflag = (toupper(*(p+1)) == 'F'))
- ++p;
- /* Set number of lines of each file to view */
- dispcnt = 65535; /* default */
- if(*(p+1)) {
- if((dispcnt = atoi(p + 1)) == 0)
- printf( "BAD COUNT %s\n", p + 1);
- }
- return;
- }
-
- if(*(p + 1) == ':') {
- /* Got a drive */
- if(isalpha(*p)) {
- if(*(p+2) == '\0') {
- /* Change output drive */
- dispcnt = 0; /* cancel previewing */
- printf("Output drive =%s\n",p);
- outdrv[0] = *p;
- return;
- }
- } else {
- printf( "ERROR - Ignoring %s\n", p);
- return;
- }
- }
-
- /* Check for ambiguous (wild-card) name */
- for(q = p; *q != '\0'; ++q)
- if(*q == '*' || *q == '?') {
- printf( "Can't accept ambiguous name %s\n", p);
- return;
- }
-
- unsqueeze(p);
- }
-
-
- unsqueeze(infile)
- char *infile;
- {
- int inbuff, outbuff; /* file buffers */
- int i, c;
- char cc;
- int fc;
-
- char *p;
- unsigned filecrc; /* checksum */
- int numnodes; /* size of decoding tree */
- char outfile[16]; /* output file name */
- unsigned linect; /* count of number of lines previewed */
-
- inbuff= open(infile,0x8000);
- if (inbuff == ERROR) {
- printf( "Can't find %s\n", infile);
- return;
- }
- /* Initialization */
- linect = 0;
- crc = 0;
- init_cr();
- init_huff();
-
- /* Process header */
- if(ugetw(inbuff) != RECOGNIZE) {
- printf( "%s is not a squeezed file\n", infile);
- goto closein;
- }
-
- filecrc = ugetw(inbuff);
-
- /* Get original file name */
- p = origname; /* send it to array */
- do {
- *p = ugetc(inbuff);
- } while(*p++ != '\0');
-
- /* Combine with output drive */
- outfile[0] = '\0'; /* empty */
- strcat(outfile, outdrv); /* drive */
- strcat(outfile, origname); /* name */
-
- /* Scan the name for illegal characters; replace them with a dash. */
-
- fc= 0;
- while (outfile[fc]) {
- if ((outfile[fc] == '/') || (outfile[fc] == '\\')) {
- printf("Illegal character in filename: ");
- printf("'%c' changed to '$'\n",outfile[fc]);
- outfile[fc]= '$';
- }
- ++fc;
- }
- printf("%s -> %s: \n", infile, outfile);
-
-
- numnodes = ugetw(inbuff);
-
- if(numnodes < 0 || numnodes >= NUMVALS) {
- printf( "%s has invalid decode tree size\n", infile);
- goto closein;
- }
-
- /* Initialize for possible empty tree (SPEOF only) */
- dnode[0].children[0] = -(SPEOF + 1);
- dnode[0].children[1] = -(SPEOF + 1);
-
- /* Get decoding tree from file */
- for(i = 0; i < numnodes; ++i) {
- dnode[i].children[0] = ugetw(inbuff);
- dnode[i].children[1] = ugetw(inbuff);
- }
-
- if(dispcnt) {
- /* Use standard output for previewing */
- putchar('\n');
- while(((c = ugetcr(inbuff)) != EOF) && (linect < dispcnt)) {
- cc = 0x7f & c; /* strip parity */
- if((cc < ' ') || (cc > '~'))
- /* Unprintable */
- switch(cc) {
- case '\r': /* return */
- /* newline will generate CR-LF */
- goto next;
- case '\n': /* newline */
- ++linect;
- case '\f': /* formfeed */
- case '\t': /* tab */
- break;
- default:
- cc = '.';
- }
- putchar(cc);
- next: ;
- }
- if(ffflag)
- putchar('\f'); /* formfeed */
- } else {
- /* Create output file */
- outbuff= creat(outfile,0x8001);
- if (outbuff == ERROR) {
- printf( "Can't create %s\n", outfile);
- goto closeall;
- }
- /* Get translated output bytes and write file */
- while((c = ugetcr(inbuff)) != EOF) {
- crc += c;
- if((uputc(c, outbuff)) == ERROR) {
- printf( "Write error in %s\n", outfile);
- goto closeall;
- }
- }
-
- if(filecrc != crc)
- printf( "ERROR - checksum error in %s\n", outfile);
-
-
- closeall:
- close(outbuff);
- }
-
- closein:
- close(inbuff);
- }
-
- /* initialize decoding functions */
-
- init_cr()
- {
- repct = 0;
- }
-
- init_huff()
- {
- bpos = 99; /* force initial read */
- }
-
- /* Get bytes with decoding - this decodes repetition,
- * calls getuhuff to decode file stream into byte
- * level code with only repetition encoding.
- *
- * The code is simple passing through of bytes except
- * that DLE is encoded as DLE-zero and other values
- * repeated more than twice are encoded as value-DLE-count.
- */
-
- int
- ugetcr(ib)
- int ib;
- {
- int c;
-
- if(repct > 0) {
- /* Expanding a repeated char */
- --repct;
- return(value);
- } else {
- /* Nothing unusual */
- if((c = getuhuff(ib)) != DLE) {
- /* It's not the special delimiter */
- value = c;
- if(value == EOF)
- repct = LARGE;
- return(value);
- } else {
- /* Special token */
- if((repct = getuhuff(ib)) == 0)
- /* DLE, zero represents DLE */
- return (DLE);
- else {
- /* Begin expanding repetition */
- repct -= 2; /* 2nd time */
- return (value);
- }
- }
- }
- }
-
- /* Decode file stream into a byte level code with only
- * repetition encoding remaining.
- */
-
- int
- getuhuff(ib)
- int ib;
- {
- int i;
- int bitval;
-
- /* Follow bit stream in tree to a leaf*/
- i = 0; /* Start at root of tree */
- do {
- if(++bpos > 7) {
- if((curin = ugetc(ib)) == ERROR)
- return (ERROR);
- bpos = 0;
- /* move a level deeper in tree */
- i = dnode[i].children[1 & curin];
- } else
- i = dnode[i].children[1 & (curin >>= 1)];
- } while(i >= 0);
-
- /* Decode fake node index to original data value */
- i = -(i + 1);
- /* Decode special endfile token to normal EOF */
- i = (i == SPEOF) ? EOF : i;
- return (i);
- }
- /* Various useful things for USQ. */
-
- char ugetc(file)
- int file;
- {
- char c;
- read(file,&c,1);
- return(c);
- }
-
- int ugetw(file)
- int file;
- {
- char cl,ch;
- cl= ugetc(file);
- ch= ugetc(file);
- return( (ch << 8) | cl);
- }
-
- int uputc(c,file)
- char c;
- int file;
- { if (write(file,&c,1) != 1)
- return(ERROR);
- return(0);
- }
- /* ATOI() function missing from Lattice C. From Kernighan and Richie. */
-
- atoi(s)
- char s[];
- {
- int i,n;
-
- n= 0;
- for (i= 0; s[i] >= '0' && s[i] <= '9'; ++i)
- n= 10*n + s[i]-'0';
- return(n);
- }
- s[i] <= '9'; ++i)
- n= 10*n + s[i]-'0';
- return(n);
- }
-